package com.zl.learning.reflect;

import org.junit.Test;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

public class MethodHandleDemo {

    public void say(String name) {
        System.out.println(name);
    }

    public static void testStatic(String name) {
        System.out.println(name);
    }

    @Test
    public void test1() {
        try {
            MethodHandle mh = MethodHandles.lookup().findVirtual(MethodHandleDemo.class, "say", MethodType.methodType(void.class, String.class));
            mh.invoke(new MethodHandleDemo(), "zhansan");
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
    }

    @Test
    public void test2() {
        try {
            Method m = MethodHandleDemo.class.getMethod("say", String.class);
            m.invoke(new MethodHandleDemo(), "lisi");
        } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void test3() {
        try {
            MethodHandle mh = MethodHandles.lookup().findStatic(MethodHandleDemo.class, "testStatic", MethodType.methodType(void.class, String.class));
            mh.invoke("zhansan");
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
    }

    @Test
    public void test4() {
        try {
            Method m = MethodHandleDemo.class.getMethod("testStatic", String.class);
            m.invoke(Method.class, "lisi");
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void test5() {
        try {
            Method m = MethodHandleDemo.class.getMethod("testStatic", String.class);
            Parameter[] parameters = m.getParameters();
            for (Parameter parameter : parameters) {
                System.out.println(parameter.getName());
                System.out.println(parameter.getType());
                System.out.println(parameter.getParameterizedType());
            }
            m.invoke(Method.class, "lisi");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
